package cn.mw.cmdb.service.impl;

import cn.mw.cmdb.entity.InstanceInfo;
import cn.mw.cmdb.entity.InstanceInfoExtend;
import cn.mw.cmdb.exception.CompoundException;
import cn.mw.cmdb.param.InstanceSearchParam;
import cn.mw.cmdb.service.InstanceSyncService;
import cn.mw.cmdb.service.ServiceAction;
import cn.mw.components.mongodb.exception.BusinessException;
import cn.mw.main.api.common.ZabbixDubboService;
import cn.mw.microMonitorCommon.constants.ZabbixApiConstants;
import cn.mw.microMonitorCommon.entity.cmdb.DataSourceInstanceVo;
import cn.mw.microMonitorCommon.entity.cmdb.DataSourceVo;
import cn.mw.microMonitorCommon.enums.DatasourceSyncMethodEnum;
import cn.mw.microMonitorCommon.enums.EngineTypeEnum;
import cn.mw.microMonitorCommon.util.SpringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static cn.mw.cmdb.processor.MonitorValue.MonitorTypeIdKey;
import static cn.mw.cmdb.processor.MonitorValue.defaultMarcos;

@Service
@Slf4j
public class InstanceSyncAddServiceImpl implements InstanceSyncService {
    @Autowired
    private CmdbServiceManage cmdbServiceManage;

    @Autowired
    private MessageSource messageSource;

    @DubboReference(check = false, timeout = 120000)
    private ZabbixDubboService zabbixDubboService;

    @Override
    public DatasourceSyncMethodEnum getDatasourceSyncMethodEnum() {
        return DatasourceSyncMethodEnum.syncAdd;
    }

    @Override
    public List<DataSourceInstanceVo> syncInstances(DataSourceVo datasourceVo, Map<DataSourceInstanceVo, InstanceInfo> dataSource2InstanceInfoMap) throws Exception {
        List<DataSourceInstanceVo> resultList = new ArrayList<>();
        List<DataSourceInstanceVo> dataSourceInstanceVoList = new ArrayList<>(dataSource2InstanceInfoMap.keySet());
        if (CollectionUtils.isEmpty(dataSourceInstanceVoList)) {
            return resultList;
        }
        Map<String, InstanceInfoExtend> hostId2InstanceMap = new HashMap<>();
        if (StringUtils.equals(EngineTypeEnum.monitorEngine.getType(), datasourceVo.getEngineType())) {
            List<String> hostIds = dataSourceInstanceVoList.stream().map(DataSourceInstanceVo::getHostId).toList();
            InstanceServiceImpl instanceService = (InstanceServiceImpl) cmdbServiceManage.getModelService(InstanceServiceImpl.ID);
            InstanceSearchParam instanceSearchParam = new InstanceSearchParam();
            Map<String, Object> dataParam = new HashMap<>();
            dataParam.put(MonitorTypeIdKey, hostIds);
            instanceSearchParam.setData(dataParam);
            List<InstanceInfoExtend> instanceInfos = instanceService.aggregateList(instanceSearchParam);
            for (InstanceInfoExtend existInstance : instanceInfos) {
                hostId2InstanceMap.put(existInstance.getMonitorTypeId(), existInstance);
            }
        }


        String webMonitorModelId = SpringUtils.getPropertiesValue("base.webMonitor.modelId");
        for (Map.Entry<DataSourceInstanceVo, InstanceInfo> entry : dataSource2InstanceInfoMap.entrySet()) {
            try {
                if (hostId2InstanceMap.containsKey(entry.getKey().getHostId())) {
                    // 主机已经存在，记录报错信息
                    entry.getKey().setErrorMsg(messageSource.getMessage("host-name-already-exists", new Object[]{entry.getKey().getName()}, LocaleContextHolder.getLocale()));
                } else {
                    cmdbServiceManage.service(entry.getValue(), ServiceAction.add);
                    if (StringUtils.equals(EngineTypeEnum.monitorEngine.getType(), datasourceVo.getEngineType())
                            && !StringUtils.equals(webMonitorModelId, datasourceVo.getTargetModelId())) {
                        // 实例id添加到主机宏中
                        zabbixDubboService.getZabbixApiResult(ZabbixApiConstants.HOST_UPDATE_MACRO, datasourceVo.getEngineId(), entry.getKey().getHostId(), defaultMarcos, entry.getValue().getId());
                    }
                    entry.getKey().setAsyncResult(true);
                    entry.getKey().setInstanceId(entry.getValue().getId());
                }
            } catch (CompoundException e) {
                StringBuffer sb = new StringBuffer(messageSource.getMessage(e.getMessageKey(), e.getArgs(), LocaleContextHolder.getLocale()));
                sb.append("[");
                for (BusinessException b : e.getExceptionList()) {
                    sb.append(messageSource.getMessage(b.getMessageKey(), b.getArgs(), LocaleContextHolder.getLocale())).append(";");
                }
                sb.append("]");
                entry.getKey().setAsyncResult(false);
                entry.getKey().setErrorMsg(sb.toString());
            } catch (BusinessException e) {
                String key = e.getMessageKey();
                String message = messageSource.getMessage(key, e.getArgs(), LocaleContextHolder.getLocale());
                entry.getKey().setAsyncResult(false);
                entry.getKey().setErrorMsg(message);
            } catch (Exception e) {
                log.error("add instanceError!", e);
                entry.getKey().setAsyncResult(false);
            }
            resultList.add(entry.getKey());
        }
        return resultList;
    }
}
